import java.util.PriorityQueue;

class MyTimerTask implements Comparable<MyTimerTask>{
    //定义出任务（在定时器中需要被执行的任务）
    private Runnable runnable;
    //任务在什么时间会被执行
    private long time;
    //写一个构造方法，去将定义出来的变量进行初始化
    public MyTimerTask(Runnable runnable,long delay){
        this.runnable=runnable;
        //任务执行的时间=当前时间+延时时间
        time=System.currentTimeMillis()+delay;
    }
    //获取任务执行的时间
    public long getTime(){
        return time;
    }
    //执行任务
    public void run(){
        runnable.run();
    }

    @Override
    public int compareTo(MyTimerTask o) {
        return (int) (this.time-o.time);
    }
}
//自己手动去实现一个定时器
class MyTimer{
//定义一个集合类，用这个集合类去保存将被执行的任务(按照时间执行的先后顺序去将任务保存到集合类中)
    //这是我们想到的是优先级队列满足我们的需求(按照时间的优先级去保存任务)
    private PriorityQueue<MyTimerTask> queue=new PriorityQueue<>();
    //使用schedule方法，按照时间的先后顺序，将任务依次保存到priorityQueue中
    public void schedule(Runnable runnable,long delay){
        synchronized (locker){
            //去创建一个MyTimerTask的实例
            MyTimerTask task=new MyTimerTask(runnable,delay);
            //按照执行任务的时间先后顺序，将任务添加到queue中
            queue.add(task);
            locker.notify();
        }
    }
    private Object locker=new Object(); //手动创建出一把锁
    //定义一个构造方法
    public MyTimer(){
        //在构造方法中去创建一个线程，执行后续代码逻辑
        Thread t =new Thread(()->{
            while (true){
                synchronized (locker){
                    //1.去瞥一下队顶元素(不取出来)
                    MyTimerTask task=queue.peek();
                    //对队列进行非空判断，防止后续造成空指针异常
                    while (task==null){
                        try {
                            locker.wait();
                            task=queue.peek();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    //将取出来的任务的执行时间与当前时间做对比
                    long curTime=System.currentTimeMillis();
                    if (curTime>=task.getTime()){
                        task.run();
                        queue.poll();
                    }
                    else {
                        try {
                            locker.wait(task.getTime()-curTime);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }

            }
        });
        t.start();
    }
}
public class Demo33 {
    public static void main(String[] args) {
          MyTimer myTimer=new MyTimer();
          myTimer.schedule(()->{
              System.out.println("hello 3000");
          },3000);
          myTimer.schedule(()->{
              System.out.println("hello 2000");
          },2000);
          myTimer.schedule(()->{
              System.out.println("hello 1000");
          },1000);
          myTimer.schedule(()->{
              System.out.println("hello 500");
          },500);
    }
}
